package main

import (
	"encoding/json"
	"fmt"
)

type tmp struct {
	x int
	y int
}

type person struct {
	name string
	age  int
}

func sum(x, y int) int {
	return x + y
}

//构造(结构体变量的)函数,返回值是对应的结构体类型
func newPerson(n string, i int) person {
	return person{
		name: n,
		age:  i,
	}
}

//方法
//接收者使用对应类型的首字母消息
//指定接收者之后，只有接收者这个类型的变量才能调用这个方法
func (p person) dream(str string) {
	fmt.Printf("%s的梦想是%s \n", p.name, str)
}

//值接收者
func (p person) guonian() {
	p.age++ //修改的是副本，此处的p,是p1的副本
}

//指针接收者，使用场景
//1.需要修改结构体变量的值时
//2.结构体本身比较大，拷贝的内存开销比较大时
//3.保持一致性：如果有一个方法使用了指针接收者，其他的方法为了统一
func (p *person) zhenguonian() {
	p.age++
}

func main() {
	//标准结构体
	var t = tmp{
		20,
		20,
	}
	fmt.Println(t)
	//匿名结构体
	var a = struct {
		x int
		y int
	}{10, 20}
	fmt.Println(a)

	var x int
	y := int8(10)
	fmt.Println(x, y)
	//1.方式1
	var p1 person //结构体先声明
	//然后实例化
	p1.name = "zl"
	p1.age = 30
	//2.方式2
	p2 := person{ //结构体声明并实例化
		"保德路",
		20,
	}
	//3.方式3
	//调用构造函数
	p3 := newPerson("ZL", 30)

	fmt.Println(p1, p2, p3)

	p1.dream("做个咸鱼")
	p2.dream("学好Go语言")

	//值接收者和指针接收者
	fmt.Println(p1.age)
	p1.guonian()
	fmt.Println(p1.age)

	fmt.Printf("%T \n", &p1)
	//(&p1).zhenguonian()
	p1.zhenguonian() //语法糖
	fmt.Println(p1.age)

	//结构体嵌套

	type addr struct {
		province string
		city     string
	}

	type student struct {
		name    string
		address addr //嵌套结构体
	}

	s := student{
		name: "zl",
		address: addr{
			"BJ",
			"HD",
		},
	}
	fmt.Println(s)

	//序列化

	type point struct {
		X int `json:"zhoulin"`
		Y int `json:"baodelu"`
	}
	po1 := point{100, 200}

	b1, err := json.Marshal(po1)
	if err != nil {
		fmt.Printf("序列化失败，err:%v \n", err)
	}
	fmt.Println(string(b1))

	//反序列化：y由字符串-->Go中的结构体变量
	str1 := `{"zhoulin":300,"baodelu":200}`
	var po2 point //造一个结构体变量，准备接收反序列化的值
	err1 := json.Unmarshal([]byte(str1), &po2)
	if err1 != nil {
		fmt.Printf("反序列化失败，err1:%v \n", err1)
	}
	fmt.Println(po2)
	fmt.Println(po2.X)
}
